package cn.ydxiaoshuai.tools.controller;

import cn.hutool.http.HttpUtil;
import cn.ydxiaoshuai.tools.base.ApiRestController;
import cn.ydxiaoshuai.tools.conts.JobConts;
import cn.ydxiaoshuai.tools.factory.AipMultiple;
import cn.ydxiaoshuai.tools.factory.BDFactory;
import cn.ydxiaoshuai.tools.util.ImageCheckUtil;
import cn.ydxiaoshuai.tools.util.MergeImageUtil;
import cn.ydxiaoshuai.tools.util.RedisUtil;
import cn.ydxiaoshuai.tools.vo.*;
import com.alibaba.fastjson.JSON;
import com.baidu.aip.face.AipFace;
import com.baidu.aip.util.Base64Util;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author 小帅丶
 * @className BaldRestController
 * @Description 秃头生成
 * @Date 2020/10/13-18:47
 **/
@Controller
@RequestMapping(value = "/rest/bald")
@Scope("prototype")
@Slf4j
public class BaldRestController extends ApiRestController{
    @Autowired
    private RedisUtil redisUtil;
    /** 人脸检测&图像处理 */
    AipMultiple aipMultiple = BDFactory.getAipMultiple();
    @Autowired
    private MergeImageUtil mergeImageUtil;

    private static final String BALD_URL = "http://180.76.188.62/predict/stgan_bald";
    /**
     * 宽
     */
    private static int MAX_WIDTH = 128;
    /**
     * 高
     */
    private static int MAX_HEIGHT = 128;

    /**
     * @Author 小帅丶
     * @Description 秃头
     * @Date  2020年10月14日
     * @param file 图片
     * @return void
     **/
    @RequestMapping(value = "/merge", method = {RequestMethod.POST})
    public ResponseEntity<Object> baldMerge(@RequestParam(value = "file") MultipartFile file) {
        log.info("=======访问的IP" + ip + "======访问的User-Agent:" + userAgent);
        BaldGeneralBean bean = new BaldGeneralBean();
        ParamBean paramBean = new ParamBean();
        try {
            startTime = System.currentTimeMillis();
            paramBean = new ParamBean(null, null, null, null, ip, userAgent);
            WXAccessToken imgCheckBean = null;
            String checkImg = redisUtil.get(JobConts.CHECK_IMG_KEY).toString();
            if (checkImg.equals(version)) {
                imgCheckBean = ImageCheckUtil.checkImg(file.getBytes(), redisUtil.get(JobConts.WXAT_KEY).toString());
                if (imgCheckBean.getErrcode() == 0) {
                    bean = dealBizz(file);
                } else {
                    bean.fail("img fail", imgCheckBean.getErrmsg(), imgCheckBean.getErrcode());
                }
            } else {
                bean = dealBizz(file);
            }
        } catch (Exception e) {
            log.info("秃头生成接口出错了" + e.getMessage());
            bean.error("error", "当前体验人数较多，请稍等~");
        }
        //耗时
        timeConsuming = String.valueOf(System.currentTimeMillis() - startTime);
        log.info("{}--耗时{},接口返回内容", requestURI,timeConsuming);
        //保存一下请求参数到redis
        redisUtil.lSet(JobConts.PARAM_KEY, paramBean);
        //保存一下结果到redis
        redisUtil.lSet(JobConts.RESULT_KEY, bean);
        //响应的内容
        return new ResponseEntity<Object>(bean, httpHeaders, HttpStatus.OK);
    }

    /**
     * @Author 小帅丶
     * @Description 字体
     * @Date  2020年10月14日
     * @return void
     **/
    @RequestMapping(value = "/font", method = {RequestMethod.GET})
    public ResponseEntity<Object> baldMerge() {
        GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
        String [] fontName=ge.getAvailableFontFamilyNames();
        List<String> bean = new ArrayList<>();
        for(int i=0;i<fontName.length;i++){
            bean.add(i,fontName[i]);
        }
        return new ResponseEntity<Object>(bean, httpHeaders, HttpStatus.OK);
    }

    /**
     * @Author 小帅丶
     * @Description 处理秃头
     * @Date  2020/10/19 15:36
     * @param file 图片对象
     * @return cn.ydxiaoshuai.tools.vo.BaldGeneralBean
     **/
    private BaldGeneralBean dealBizz(MultipartFile file) throws Exception {
        BaldGeneralBean bean;
        //人脸检测以及数量检测
        bean = checkFace(file);
        if (bean.getCode() == 200) {
            //缩放图片
            if (redisUtil.get(JobConts.ZOOM_KEY).toString().equals(JobConts.ZOOM_VALUE_1)) {
                bean = getBaldResults(file,bean);
            } else {
                bean = getBaldResults(file,bean);
            }
        } else {
            return bean;
        }
        return bean;

    }

    private BaldGeneralBean getBaldResults(MultipartFile file,BaldGeneralBean bean){
        BaldRequestBean requestBean =  new BaldRequestBean();
        JSONObject newData0 = new JSONObject();
        JSONObject newData1 = new JSONObject();
        JSONObject newData2 = new JSONObject();
        try {
            List<String> images = new ArrayList<>();
            images.add(Base64Util.encode(file.getBytes()));
            requestBean.setImages(images);
            String baldResult = HttpUtil.post(BALD_URL,JSON.toJSONString(requestBean));
            BaldResponseBean responseBean = JSON.parseObject(baldResult,BaldResponseBean.class);
            if(responseBean.getStatus().equals("0")){
                BaldResponseBean.ResultsBean data = responseBean.getResults();

                String newData0BGR = convertBGR(data.getData_0());
                newData0 = aipMultiple.imageDefinitionEnhance(newData0BGR);
                if(newData0.has("error_code")){
                    log.info("1年错误信息{}",newData1.toString());
                    if(newData0.get("error_code").toString().equals("216201")){
                        data.setData_0(newData0BGR);
                    }else{
                        data.setData_0(newData0BGR);
                    }
                }else{
                    data.setData_0(newData0.getString("image"));
                }

                String newData1BGR = convertBGR(data.getData_1());
                newData1 = aipMultiple.imageDefinitionEnhance(newData1BGR);
                if(newData1.has("error_code")){
                    log.info("3年错误信息{}",newData1.toString());
                    if(newData1.get("error_code").toString().equals("216201")){
                        data.setData_1(newData1BGR);
                    }else{
                        data.setData_1(newData1BGR);
                    }
                }else{
                    data.setData_1(newData1.getString("image"));
                }

                String newData2BGR = convertBGR(data.getData_2());
                newData2 = aipMultiple.imageDefinitionEnhance(newData2BGR);
                if(newData2.has("error_code")){
                    log.info("5年错误信息{}",newData2.toString());
                    if(newData2.get("error_code").toString().equals("216201")){
                        data.setData_2(newData2BGR);
                    }else{
                        data.setData_2(newData2BGR);
                    }
                }else{
                    data.setData_2(newData2.getString("image"));
                }
                data.setJobNum(mergeImageUtil.SeqGenerator("A",4));
                bean.success("ok", "成功", data);
            }else{
                log.info("秃头转换失败{}",baldResult);
                bean.fail("fail","秃头转换失败",80500);
            }
        }catch (Exception e){
            bean.error("error", "当前体验人数较多，请稍等~");
        }
        return bean;
    }

    /**
     *
     * @param data
     * @return
     * @throws Exception
     */
    private String convertBGR(String data) throws Exception {
        byte[] imgBytes = Base64Util.decode(data);
        ByteArrayInputStream byteBaldImg = new ByteArrayInputStream(imgBytes);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        BufferedImage bufferedImage = ImageIO.read(byteBaldImg);
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();
        // 获取图片中每个rgb像素的int类型表示
        int[] rgbPixels = bufferedImage.getRGB(0, 0, width, height, null, 0, width);
        int[] bgrPixels = new int[rgbPixels.length];
        for (int i = 0; i < rgbPixels.length; i++) {
            int color = rgbPixels[i];
            int red = ((color & 0x00FF0000) >> 16);
            int green = ((color & 0x0000FF00) >> 8);
            int blue = color & 0x000000FF;
            // 将rgb三个通道的数值合并为一个int数值，同时调换b通道和r通道
            bgrPixels[i] = (red & 0x000000FF) | (green << 8 & 0x0000FF00) | (blue << 16 & 0x00FF0000);
        }
        bufferedImage.setRGB(0, 0, width, height, bgrPixels, 0, width);
        ImageIO.write(bufferedImage, "jpg", outputStream);
        String base64 = Base64Util.encode(outputStream.toByteArray());
        return base64;
    }

    /**
     * @Author 小帅丶
     * @Description 检测是否包含人脸以及人脸数量
     * @Date  2020/10/19 15:36
     * @param file 图片对象
     * @return cn.ydxiaoshuai.tools.vo.BaldGeneralBean
     **/
    private BaldGeneralBean checkFace(MultipartFile file) throws Exception{
        BaldGeneralBean bean = new BaldGeneralBean();
        HashMap<String,String> options = new HashMap<>();
        options.put("max_face_num", "10");
        options.put("face_field", "age,beauty,gender,glasses,mask");
        JSONObject object = aipMultiple.detect(Base64Util.encode(file.getBytes()), "BASE64",options);
        FaceV3DetectBean faceBean = JSON.parseObject(object.toString(),FaceV3DetectBean.class);
        if (faceBean.getError_code()==222202) {
            bean.fail(object.get("error_msg").toString(), "图片中不包含人脸", Integer.parseInt(object.get("error_code").toString()));
        } else if (faceBean.getError_code()==0) {
            Integer faceNum = faceBean.getResult().getFace_num();
            if(faceNum==1){
                bean.success("ok", "人脸数量正确");
            } else {
                bean.fail("face_num size large", "确保图中只包含一个人脸", 85004);
            }
        } else {
            bean.fail(object.get("error_msg").toString(), object.get("error_msg").toString(), Integer.parseInt(object.get("error_code").toString()));
        }
        return bean;
    }
}
